﻿/*
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package 
{
	import flash.net.Socket;
	import flash.events.*;
	import flash.net.URLLoader;
    import flash.net.URLRequest;
	import flash.filesystem.*; 
	
	public class FTPUpload extends EventDispatcher
	{
		private var username = "username";
		private var password = "password";
		private var hostname = "ftp.hostname.com";
		private var port = 21;

		private var fileUpload = "updatedata.xml"; //TODO: hardcoded - TBC
		private var s:Socket;
		
		var ftp_response:String;
		var ftp_response_code:Number;
		var data_response:String;
		var data_channel_ip:String;
		var data_channel_port:int;
		var data_channel:Socket;
		var i_bytes_send:int;
		var i_block_count:int;
		
		public function FTPUpload(username:String, password: String, hostname:String)
		{
			this.hostname = hostname;
		}
		
		public function uploadAndTest(){
			s = new Socket(hostname,port);
			s.addEventListener(ProgressEvent.SOCKET_DATA, dataGet);
		}

		private function dataGet(e:Event)
		{
			try
			{
				ftp_response = s.readUTFBytes(s.bytesAvailable);
				ftp_response_code = Number(ftp_response.substr(0,3));
				if (ftp_response_code == 220)
				{
					//connected to ftp server send username to server
					s.writeUTFBytes("USER "+username+"\n");
					s.flush();
				}
				if (ftp_response_code == 331)
				{
					//Username accepted now send password to server
					s.writeUTFBytes("PASS "+password+"\n");
					s.flush();
				}
				
				if (ftp_response_code == 230)
				{
					s.writeUTFBytes("CWD \n");
					s.flush();
					
					s.writeUTFBytes("PASV \n");
					s.flush();
				}
				
				//Entering passive mode
				if (ftp_response_code == 227)
				{
					
					var temp = ftp_response.substring(ftp_response.indexOf("(") + 1,ftp_response.indexOf(")"));
					var data_channel_temp = temp.split(",");

					data_channel_ip = data_channel_temp.slice(0,4).join(".");

					//calculate the port number from the last two digits
					data_channel_port = parseInt(data_channel_temp[4]) * 256 + int(data_channel_temp[5]);

					//use the new IP to open a second socket - this will transmit the data. Your first socket will transmit any commands you issue and this new socket will transmit the data
					data_channel = new Socket(data_channel_ip,data_channel_port);

					data_channel.addEventListener(ProgressEvent.SOCKET_DATA, receiveData);
					//data_channel.addEventListener(IOErrorEvent.IO_ERROR, showError);
					//data_channel.addEventListener(SecurityErrorEvent.SECURITY_ERROR, showSecError);
					data_channel.addEventListener(Event.CONNECT, dataConnect);



				}
				if (ftp_response.indexOf('226') > -1)
				{
					dispatchEvent(new Event(Event.COMPLETE,false,false));
					s.close();
					
				}
				trace(ftp_response);
				
			}
			catch (errObject:Error)
			{
				trace("\nCatch The message is: " + errObject.message);
			}
		}

		function receiveData(e:ProgressEvent):void
		{
			try
			{
				data_response = data_channel.readUTFBytes(data_channel.bytesAvailable);
				trace('DATA: ' + data_response);
			}
			catch (errObject:Error)
			{
				trace("\nCatch The message is: " + errObject.message);
			}
		}

		function onComplete(e:Event):void
		{
			s.writeUTFBytes("TYPE I");
			sendSocket(s);
			s.writeUTFBytes("PASV");
			sendSocket(s);
		}
		function sendSocket(s:Socket):void
		{

			s.writeByte( 13 );
			s.writeByte( 10 );
			s.flush();
		}

		function dataConnect(e:Event):void
		{
			try
			{
				SaveFile();
				FileTransfer();
			}
			catch (errObject:Error)
			{
				trace("\nCatch The message is: " + errObject.message);
			}
		}
		
		private function _configureListeners(dispatcher:IEventDispatcher):void {
            dispatcher.addEventListener(Event.COMPLETE, _onComplete);
        }
		
		private function _onComplete(event:Event):void{
			//TODO: add progress update
			var i_block_size:int = 1024;// bytes
			
			var repeatcount:int = Math.floor(event.currentTarget.bytesTotal / i_block_size);
			var remainder:int = event.currentTarget.bytesTotal - (repeatcount * i_block_size);
			i_bytes_send = 0;
			
			data_channel.writeUTFBytes(event.currentTarget.data);
			data_channel.flush();			
			data_channel.close();
		}

		function FileTransfer()
		{
			var XMLURL:URLRequest = new URLRequest(fileUpload);
			var XMLLoader:URLLoader = new URLLoader();
			_configureListeners(XMLLoader);
			try {
                XMLLoader.load(XMLURL);
            } catch (error:Error) {
                trace("Unable to load configuration file.");
            }
			
		}
		function SaveFile()
		{
			s.writeUTFBytes("STOR " + fileUpload);
			sendSocket(s);
		}
		
	}

}